package com.zenithmind.note.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.note.mapper.CommentLikeMapper;
import com.zenithmind.note.mapper.NoteCommentMapper;
import com.zenithmind.note.mapper.NoteMapper;
import com.zenithmind.note.pojo.dto.NoteCommentDTO;
import com.zenithmind.note.pojo.entity.CommentLike;
import com.zenithmind.note.pojo.entity.Note;
import com.zenithmind.note.pojo.entity.NoteComment;
import com.zenithmind.note.pojo.query.NoteCommentQuery;
import com.zenithmind.note.pojo.query.UserCommentQuery;
import com.zenithmind.note.pojo.vo.NoteCommentVO;
import com.zenithmind.note.service.NoteCommentService;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.exception.UnauthorizedException;
import com.zenithmind.common.annotation.DataCache;
import com.zenithmind.common.annotation.DataCacheEvict;
import com.zenithmind.common.constant.CacheConstants;
import com.zenithmind.common.security.SecurityUtils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 笔记评论服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NoteCommentServiceImpl extends ServiceImpl<NoteCommentMapper, NoteComment> implements NoteCommentService {
    
    private final NoteMapper noteMapper;
    private final CommentLikeMapper commentLikeMapper;
    
    // 缓存相关常量
    private static final String CACHE_COMMENT_PREFIX = "note:comment";
    private static final String CACHE_NOTE_COMMENTS_PREFIX = "note:comments";
    private static final String CACHE_USER_COMMENTS_PREFIX = "user:comments";
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = CACHE_NOTE_COMMENTS_PREFIX, key = "#noteCommentDTO.noteId")
    public NoteComment createComment(NoteCommentDTO noteCommentDTO, String userId) {
        // 获取笔记信息，确认笔记存在
        Note note = noteMapper.selectById(noteCommentDTO.getNoteId());
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 创建评论
        NoteComment comment = new NoteComment();
        BeanUtils.copyProperties(noteCommentDTO, comment);
        comment.setUserId(userId);
        comment.setLikeCount(0);
        this.save(comment);
        
        // 更新笔记评论数
        note.setCommentCount(note.getCommentCount() + 1);
        noteMapper.updateById(note);
        
        return comment;
    }
    
    /**
     * 创建评论 - 使用CurrentUserHolder获取用户ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public NoteComment createComment(NoteCommentDTO commentDTO) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 获取笔记信息，确认笔记存在
        Note note = noteMapper.selectById(commentDTO.getNoteId());
        if (note == null) {
            throw new RuntimeException("笔记不存在");
        }
        
        // 创建评论
        NoteComment comment = new NoteComment();
        BeanUtils.copyProperties(commentDTO, comment);
        comment.setUserId(userId);
        comment.setLikeCount(0);
        this.save(comment);
        
        // 更新笔记评论数
        note.setCommentCount(note.getCommentCount() + 1);
        noteMapper.updateById(note);
        
        return comment;
    }

    /**
     * 删除评论 - 使用CurrentUserHolder获取用户ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteComment(String commentId) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 查询评论
        NoteComment comment = this.getById(commentId);
        if (comment == null) {
            throw new RuntimeException("评论不存在");
        }
        
        // 检查权限：自己的评论或者笔记的作者
        Note note = noteMapper.selectById(comment.getNoteId());
        if (!comment.getUserId().equals(userId) && !note.getUserId().equals(userId)) {
            throw new RuntimeException("无权删除该评论");
        }
        
        // 删除评论
        this.removeById(commentId);
        
        // 删除子评论
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getParentId, commentId);
        this.remove(wrapper);
        
        // 更新笔记评论数
        note.setCommentCount(Math.max(0, note.getCommentCount() - 1));
        noteMapper.updateById(note);
    }

    /**
     * 删除评论 - 外部传入用户ID
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = CACHE_COMMENT_PREFIX, key = "#commentId")
    public void deleteComment(String commentId, String userId) {
        // 查询评论
        NoteComment comment = this.getById(commentId);
        if (comment == null) {
            throw new RuntimeException("评论不存在");
        }
        
        // 检查权限：自己的评论或者笔记的作者
        Note note = noteMapper.selectById(comment.getNoteId());
        if (!comment.getUserId().equals(userId) && !note.getUserId().equals(userId)) {
            throw new RuntimeException("无权删除该评论");
        }
        
        // 删除评论
        this.removeById(commentId);
        
        // 删除子评论
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getParentId, commentId);
        this.remove(wrapper);
        
        // 更新笔记评论数
        note.setCommentCount(Math.max(0, note.getCommentCount() - 1));
        noteMapper.updateById(note);
    }

    /**
     * 获取笔记评论列表 - 使用CurrentUserHolder获取用户ID
     */
    @Override
    @DataCache(prefix = CACHE_NOTE_COMMENTS_PREFIX, key = "#noteId", expireTime = CacheConstants.TTL_SECONDS_DEFAULT)
    public List<NoteCommentVO> getCommentsByNoteId(String noteId) {
        // 直接在方法内获取用户ID
        String userId = SecurityUtils.getCurrentUserId();
        
        // 查询所有评论
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getNoteId, noteId)
                .orderByDesc(NoteComment::getCreateTime);
        List<NoteComment> comments = this.list(wrapper);
        
        if (comments.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 获取所有评论ID
        List<String> commentIds = comments.stream()
                .map(NoteComment::getId)
                .collect(Collectors.toList());
        
        // 查询用户是否点赞
        Map<String, Boolean> likeMap = Collections.emptyMap();
        if (userId != null) {
            LambdaQueryWrapper<CommentLike> likeWrapper = Wrappers.<CommentLike>lambdaQuery()
                    .eq(CommentLike::getUserId, userId)
                    .in(CommentLike::getCommentId, commentIds);
            List<CommentLike> likes = commentLikeMapper.selectList(likeWrapper);
            
            likeMap = likes.stream()
                    .collect(Collectors.toMap(CommentLike::getCommentId, like -> true));
        }
        
        // 构建评论树
        Map<String, Boolean> finalLikeMap = likeMap;
        Map<String, List<NoteComment>> parentMap = comments.stream()
                .filter(c -> c.getParentId() != null)
                .collect(Collectors.groupingBy(NoteComment::getParentId));
        
        return comments.stream()
                .filter(c -> c.getParentId() == null)
                .map(comment -> buildCommentVO(comment, parentMap, finalLikeMap, userId))
                .collect(Collectors.toList());
    }

    /**
     * 获取笔记评论列表 - 外部传入用户ID
     */
    @Override
    @DataCache(prefix = CACHE_NOTE_COMMENTS_PREFIX, key = "#noteId + ':' + #userId", expireTime = CacheConstants.TTL_SECONDS_DEFAULT)
    public List<NoteCommentVO> getCommentsByNoteId(String noteId, String userId) {
        // 查询所有评论
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getNoteId, noteId)
                .orderByDesc(NoteComment::getCreateTime);
        List<NoteComment> comments = this.list(wrapper);
        
        if (comments.isEmpty()) {
            return Collections.emptyList();
        }
        
        // 获取所有评论ID
        List<String> commentIds = comments.stream()
                .map(NoteComment::getId)
                .collect(Collectors.toList());
        
        // 查询用户是否点赞
        Map<String, Boolean> likeMap = Collections.emptyMap();
        if (userId != null) {
            LambdaQueryWrapper<CommentLike> likeWrapper = Wrappers.<CommentLike>lambdaQuery()
                    .eq(CommentLike::getUserId, userId)
                    .in(CommentLike::getCommentId, commentIds);
            List<CommentLike> likes = commentLikeMapper.selectList(likeWrapper);
            
            likeMap = likes.stream()
                    .collect(Collectors.toMap(CommentLike::getCommentId, like -> true));
        }
        
        // 构建评论树
        Map<String, Boolean> finalLikeMap = likeMap;
        Map<String, List<NoteComment>> parentMap = comments.stream()
                .filter(c -> c.getParentId() != null)
                .collect(Collectors.groupingBy(NoteComment::getParentId));
        
        return comments.stream()
                .filter(c -> c.getParentId() == null)
                .map(comment -> buildCommentVO(comment, parentMap, finalLikeMap, userId))
                .collect(Collectors.toList());
    }

    /**
     * 点赞/取消点赞评论
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @DataCacheEvict(prefix = CACHE_COMMENT_PREFIX, key = "#commentId")
    public Result<Boolean> toggleCommentLike(String commentId) {
        // 直接在方法内获取用户ID并验证
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new BusinessException("用户未登录");
        }

        // 查询评论
        NoteComment comment = this.getById(commentId);
        if (comment == null) {
            throw new BusinessException("评论不存在");
        }
        
        // 查询是否已点赞
        LambdaQueryWrapper<CommentLike> wrapper = Wrappers.<CommentLike>lambdaQuery()
                .eq(CommentLike::getCommentId, commentId)
                .eq(CommentLike::getUserId, userId);
        CommentLike like = commentLikeMapper.selectOne(wrapper);
        
        if (like != null) {
            // 已点赞，取消点赞
            commentLikeMapper.deleteById(like.getId());
            
            // 更新评论点赞数
            comment.setLikeCount(Math.max(0, comment.getLikeCount() - 1));
            this.updateById(comment);
            return Result.success(false);
        } else {
            // 未点赞，添加点赞
            like = new CommentLike();
            like.setCommentId(commentId);
            like.setUserId(userId);
            commentLikeMapper.insert(like);
            
            // 更新评论点赞数
            comment.setLikeCount(comment.getLikeCount() + 1);
            this.updateById(comment);
            return Result.success(true);
        }
    }
    
    /**
     * 查询用户的评论列表 - 使用CurrentUserHolder获取用户ID
     */
    @Override
    public PageResult<NoteCommentVO> getUserComments(long current, long size) {
        // 直接在方法中获取用户ID并进行校验
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 分页查询用户的评论
        Page<NoteComment> page = new Page<>(current, size);
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getUserId, userId)
                .orderByDesc(NoteComment::getCreateTime);
        
        Page<NoteComment> commentPage = this.page(page, wrapper);
        
        if (commentPage.getRecords().isEmpty()) {
            return new PageResult<>(Collections.emptyList(), commentPage.getTotal(), commentPage.getCurrent(), commentPage.getSize());
        }
        
        // 获取所有评论ID
        List<String> commentIds = commentPage.getRecords().stream()
                .map(NoteComment::getId)
                .collect(Collectors.toList());
        
        // 查询用户是否点赞
        LambdaQueryWrapper<CommentLike> likeWrapper = Wrappers.<CommentLike>lambdaQuery()
                .eq(CommentLike::getUserId, userId)
                .in(CommentLike::getCommentId, commentIds);
        List<CommentLike> likes = commentLikeMapper.selectList(likeWrapper);
        
        Map<String, Boolean> likeMap = likes.stream()
                .collect(Collectors.toMap(CommentLike::getCommentId, like -> true));
        
        // 转换为VO
        List<NoteCommentVO> commentVOs = commentPage.getRecords().stream()
                .map(comment -> {
                    NoteCommentVO vo = new NoteCommentVO();
                    BeanUtils.copyProperties(comment, vo);
                    vo.setLiked(likeMap.getOrDefault(comment.getId(), false));
                    return vo;
                })
                .collect(Collectors.toList());
        
        return new PageResult<>(commentVOs, commentPage.getTotal(), commentPage.getCurrent(), commentPage.getSize());
    }

    /**
     * 构建评论VO，包含子评论
     */
    private NoteCommentVO buildCommentVO(NoteComment comment, Map<String, List<NoteComment>> parentMap, 
                                         Map<String, Boolean> likeMap, String userId) {
        NoteCommentVO vo = new NoteCommentVO();
        BeanUtils.copyProperties(comment, vo);
        vo.setLiked(likeMap.getOrDefault(comment.getId(), false));
        
        // 添加子评论
        List<NoteComment> children = parentMap.getOrDefault(comment.getId(), Collections.emptyList());
        if (!children.isEmpty()) {
            vo.setChildren(children.stream()
                    .map(child -> {
                        NoteCommentVO childVo = new NoteCommentVO();
                        BeanUtils.copyProperties(child, childVo);
                        childVo.setLiked(likeMap.getOrDefault(child.getId(), false));
                        return childVo;
                    })
                    .collect(Collectors.toList()));
        } else {
            vo.setChildren(new ArrayList<>());
        }
        
        return vo;
    }

    /**
     * 后台管理-分页查询评论
     */
    @Override
    public PageResult<NoteCommentVO> commentManagePage(NoteCommentQuery query) {
        // 获取Page对象
        Page<NoteComment> page = query.toPage();
        
        // 构建查询条件
        LambdaQueryWrapper<NoteComment> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(query.getNoteId() != null && !query.getNoteId().isEmpty(), NoteComment::getNoteId, query.getNoteId())
              .eq(query.getUserId() != null, NoteComment::getUserId, query.getUserId())
              .eq(query.getStatus() != null, NoteComment::getStatus, query.getStatus())
              .like(StringUtils.isNotBlank(query.getKeyword()), NoteComment::getContent, query.getKeyword())
              .orderByDesc(NoteComment::getCreateTime);
        
        // 执行分页查询
        Page<NoteComment> commentPage = page(page, wrapper);
        
        // 转换为VO列表
        List<NoteCommentVO> commentVOList = commentPage.getRecords().stream()
            .map(comment -> {
                NoteCommentVO commentVO = new NoteCommentVO();
                BeanUtils.copyProperties(comment, commentVO);
                return commentVO;
            })
            .collect(Collectors.toList());
        
        // 返回分页结果
        return new PageResult<>(
            commentVOList,
            commentPage.getTotal(),
            commentPage.getCurrent(),
            commentPage.getSize()
        );
    }

    /**
     * 后台管理-获取评论详情
     */
    @Override
    @DataCache(prefix = CACHE_COMMENT_PREFIX, key = "#commentId", expireTime = CacheConstants.TTL_SECONDS_DEFAULT)
    public NoteCommentVO getCommentById(String commentId) {
        NoteComment comment = getById(commentId);
        if (comment == null) {
            throw new RuntimeException("评论不存在");
        }
        
        // 转换为VO并返回
        NoteCommentVO commentVO = new NoteCommentVO();
        BeanUtils.copyProperties(comment, commentVO);
        return commentVO;
    }

    /**
     * 后台管理-添加或修改评论
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_COMMENT_PREFIX, key = "#comment.id")
    public NoteCommentVO addOrUpdateComment(NoteComment comment) {
        // 如果是修改操作
        if (StringUtils.isNotBlank(comment.getId())) {
            NoteComment existingComment = getById(comment.getId());
            if (existingComment == null) {
                throw new RuntimeException("评论不存在");
            }
            
            // 更新评论
            updateById(comment);
        } else {
            // 新增评论
            // 初始化计数器
            if (comment.getLikeCount() == null) {
                comment.setLikeCount(0);
            }
            save(comment);
        }
        
        // 返回更新后的评论信息
        NoteCommentVO commentVO = new NoteCommentVO();
        BeanUtils.copyProperties(getById(comment.getId()), commentVO);
        return commentVO;
    }

    /**
     * 后台管理-批量删除评论
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_COMMENT_PREFIX, allEntries = true)
    public void deleteBatch(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return;
        }
        
        log.info("批量删除评论：{}", ids);
        
        try {
            // 分批处理，每次最多处理100条
            int batchSize = 100;
            int total = ids.size();
            
            for (int i = 0; i < total; i += batchSize) {
                int end = Math.min(i + batchSize, total);
                List<String> batch = ids.subList(i, end);
                
                // 执行批量删除
                removeByIds(batch);
            }
        } catch (Exception e) {
            log.error("批量删除评论失败：{}", e.getMessage(), e);
            throw new RuntimeException("批量删除评论失败", e);
        }
    }

    /**
     * 后台管理-批量更新评论状态
     */
    @Override
    @Transactional
    @DataCacheEvict(prefix = CACHE_NOTE_COMMENTS_PREFIX, allEntries = true)
    public void batchUpdateStatus(List<String> ids, Integer status) {
        if (ids == null || ids.isEmpty() || status == null) {
            return;
        }
        
        ids.forEach(id -> {
            NoteComment comment = getById(id);
            if (comment != null) {
                comment.setStatus(status);
                updateById(comment);
            }
        });
    }

    /**
     * 查询用户的评论列表 - 使用查询对象
     *
     * @param query 查询对象
     * @return 分页结果
     */
    @Override
    @DataCache(prefix = CACHE_USER_COMMENTS_PREFIX, key = "#query.userId + ':' + #query.current + ':' + #query.size", 
                expireTime = CacheConstants.TTL_SECONDS_USER)
    public PageResult<NoteCommentVO> getUserCommentPage(UserCommentQuery query) {
        String userId = SecurityUtils.getCurrentUserId();
        if (StringUtils.isBlank(userId)) {
            throw new UnauthorizedException("用户未登录");
        }
        
        // 创建分页对象
        Page<NoteComment> page = query.toPage();
        
        // 构建查询条件
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getUserId, userId)
                .eq(query.getStatus() != null, NoteComment::getStatus, query.getStatus())
                .orderByDesc(NoteComment::getCreateTime);
        
        Page<NoteComment> commentPage = this.page(page, wrapper);
        
        if (commentPage.getRecords().isEmpty()) {
            return new PageResult<>(Collections.emptyList(), commentPage.getTotal(), commentPage.getCurrent(), commentPage.getSize());
        }
        
        // 获取所有评论ID
        List<String> commentIds = commentPage.getRecords().stream()
                .map(NoteComment::getId)
                .collect(Collectors.toList());
        
        // 查询用户是否点赞
        LambdaQueryWrapper<CommentLike> likeWrapper = Wrappers.<CommentLike>lambdaQuery()
                .eq(CommentLike::getUserId, userId)
                .in(CommentLike::getCommentId, commentIds);
        List<CommentLike> likes = commentLikeMapper.selectList(likeWrapper);
        
        Map<String, Boolean> likeMap = likes.stream()
                .collect(Collectors.toMap(CommentLike::getCommentId, like -> true));
        
        // 转换为VO
        List<NoteCommentVO> commentVOs = commentPage.getRecords().stream()
                .map(comment -> {
                    NoteCommentVO vo = new NoteCommentVO();
                    BeanUtils.copyProperties(comment, vo);
                    vo.setLiked(likeMap.getOrDefault(comment.getId(), false));
                    return vo;
                })
                .collect(Collectors.toList());
        
        return new PageResult<>(commentVOs, commentPage.getTotal(), commentPage.getCurrent(), commentPage.getSize());
    }

    /**
     * 分页查询用户的评论列表 - 外部传入用户ID
     */
    @Override
    @DataCache(prefix = CACHE_USER_COMMENTS_PREFIX, key = "#userId + ':' + #current + ':' + #size", 
                expireTime = CacheConstants.TTL_SECONDS_USER)
    public PageResult<NoteCommentVO> getUserComments(String userId, long current, long size) {
        // 分页查询用户的评论
        Page<NoteComment> page = new Page<>(current, size);
        LambdaQueryWrapper<NoteComment> wrapper = Wrappers.<NoteComment>lambdaQuery()
                .eq(NoteComment::getUserId, userId)
                .orderByDesc(NoteComment::getCreateTime);
        
        Page<NoteComment> commentPage = this.page(page, wrapper);
        
        if (commentPage.getRecords().isEmpty()) {
            return new PageResult<>(Collections.emptyList(), commentPage.getTotal(), commentPage.getCurrent(), commentPage.getSize());
        }
        
        // 获取所有评论ID
        List<String> commentIds = commentPage.getRecords().stream()
                .map(NoteComment::getId)
                .collect(Collectors.toList());
        
        // 查询用户是否点赞
        LambdaQueryWrapper<CommentLike> likeWrapper = Wrappers.<CommentLike>lambdaQuery()
                .eq(CommentLike::getUserId, userId)
                .in(CommentLike::getCommentId, commentIds);
        List<CommentLike> likes = commentLikeMapper.selectList(likeWrapper);
        
        Map<String, Boolean> likeMap = likes.stream()
                .collect(Collectors.toMap(CommentLike::getCommentId, like -> true));
        
        // 转换为VO
        List<NoteCommentVO> commentVOs = commentPage.getRecords().stream()
                .map(comment -> {
                    NoteCommentVO vo = new NoteCommentVO();
                    BeanUtils.copyProperties(comment, vo);
                    vo.setLiked(likeMap.getOrDefault(comment.getId(), false));
                    return vo;
                })
                .collect(Collectors.toList());
        
        return new PageResult<>(commentVOs, commentPage.getTotal(), commentPage.getCurrent(), commentPage.getSize());
    }
} 